Modding
Create your first mod for UBOAT 1. Launch the game launcher. 2. Select "Mods" tab. 3. Click "Create new mod". 4. Fill out the form and choose template that suits your needs. "Unity project" template opens up the most modding possibilities although requires to use Unity Editor. "Empty project" may be preferred for quick mods such as mods altering the game data sheets, replacing a few assets or adding simple scripts. 5. That's all, let's start actual modding. Basics of modding In this section you will learn how to mod basic things in the game that don't require the use of Unity Editor. Mod structure Final mod that is ready to install on a user's computer should contain a few special files and folders. Bundles: This folder should contain all asset bundles supplied by your mod. Asset bundles are packed Unity files that are meant to contain models, textures, audio files and other game assets. All files in this folder are usually packed automatically by scripts that are supplied with "Unity project" template. Data Sheets: This is the place for all Excel data sheets of your mod that can either override or extend base game data or contain custom data that is recognized and used by your mod scripts. Source: Mod's script files should land here in a raw form. They are compiled by the game on the fly. Manifest.json: Each mod has to contain such file directly in the main folder. It's created automatically when a new mod is created by the game's launcher. It's purpose is to define your mod's name, description and security permissions for its code. This file can be edited freely. Preview (png or jpg): It's an icon for your mod. It's displayed in the game's launcher in your mod's description section and on Steam Workshop. All other folders and files are ignored by the game, like the "Templates" folder in the example above. It's not a special folder, but a custom folder that groups files, that are used by this concrete mod scripts. Game data files Default files Default game data files can be viewed by going into the installation folder and opening files located in this folder: path_to_uboat\UBOAT_Data\Data Sheets\ These are Excel files. They may be opened by various software including Microsoft Office, Open Office or Microsoft Excel Online. All of these files contains multiple sheets (these are the tabs on the bottom) and are structured in such a way that there are multiple grouping rows followed by rows with actual data. Take a look at this example taken from General.xlsx / Settings: In this example, there are overall three data rows grouped into two categories - Weather and Audio. In this wiki we will refer to specific properties by specifying their full path containing a file name, sheet name, grouping category and ID of the data row (first column) like in these examples: * General.xlsx / Settings / Weather / Dynamism * General.xlsx / Settings / Audio / Compartment Wall Damping * General.xlsx / Settings / Audio / Hull Thickness Overrides In this section we will discuss how to override data from the default data files in a mod. As an example, we will alter how fast officers become tired and loose energy without editing original data sheets. This value is located at: "General.xlsx / Settings / Energy / Gain Scale" row. To override this value or any other value in the game, these are the steps to do it: # Create "Data Sheets" folder inside your mod folder. # Create a new empty Excel sheet (.xlsx) with the same name as the one in which you want to replace some values (General.xlsx in this example). # Create tab with the same name as the tab in which you want to replace things ("Settings" in this example). # Create grouping category, if such grouping exists ("/Energy" in this example - you can copy-paste it from the original sheet). # Create row with the same value of the first cell (it's ID), but with other cells altered to your liking. # Done. Mod will replace this value. Please note that the order in which mods are loaded determines which mod will write the final value. Game first loads default game data and then loads mods one by one from the first to the last one in the order specified in the game's launcher and adds/replaces data from their data sheets. Final file in this example should be named "General.xlsx" and look like on the screenshot below. You can download the final file for this sample from this link. Adding new data Most data sheets are open ended, which means that the controlling script will read and parse all rows with unique IDs. For example, convoys are defined in "Sandbox.xlsx / Spawners". If your mod contains rows with unique IDs in the first cell (not present in the original data sheets), it will add new convoys instead of overriding values for the existing ones. Unity project workflows Setup Unity Setup Install the Unity Hub. The asset project requires Unity 2018.2.21. It's not available within the Hub installer, you'll need to download it separately from the Unity Download Archive. Add Editor to Hub In the Unity Hub, choose "Installs" from the left-hand menu, and click "Locate". Navigate to the Unity.exe application within your install location (ex: Unity Editors\2018.2.21f1\Editor\Unity.exe) Add Project to Hub Under the Projects tab in Hub, click "Add" and navigate to the folder the Uboat Launcher created for your mod. It should now show up under available projects. NOTE: if you do not have Unity 2018.2.21 installed, it will not let you open the project. Launch Editor Launch Unity Editor, enter Edit menu > Preferences > click "UBOAT Modding" tab. You may want to adjust these settings to your liking. Remember to set a path to your game - this is required. After you set a path, modding tools script will link all needed game assemblies and resources from the game folder to your project. If your editor was configured previously and already had a game executable path set or assemblies weren't copied for other reasons, click "Update Game Assemblies" from the "Tools" menu to trigger this process manually. Everything should be ready to start at this point. Running your project After your project was created you will have to launch the game launcher and enable your mod there. From this point you can press "Play" in Unity Editor to test your mod. Our modding scripts built into the editor override behavior of this button and launch the game instead of the editor's play mode. If you don't like this you can disable it in the preferences and instead use the menu command at "Tools/Deploy Mods and Launch" as it does the same thing. Project structure Assets/Mods: This folder contains all mods in this project in their final form like described in the Basics of modding section. These are the final files for the mod that are recognized by the game and distributed to the end users. All files in this folder can be created and edited manually except the "Bundles" sub-folder inside each mod folder. All files in these sub-folders are created automatically. Assets/Packages: This is a folder that contains all assets (models, textures, audio files etc.) that will be used by the mods in this project. Each sub-folder at this location must correspond to exactly one asset bundle and should either have the same name as the mod that will use the assets inside or have any custom suffix after a dot like this: "modname.custombundlename". This folder's name is in a small naming collision with Unity's own "Packages" folder. We were using this name before this folder was introduced into Unity and we will probably maintain it for backwards compatibility. Aside from occasional mistaking of these folders, this doesn't cause any actual problems. Asset replacement The easiest way to replace assets in the game is to use our UBOAT Inspector mod to browse the assets inside the game and unpack them into your mod folder for modifications. 1. Run the game with UBOAT Inspector mod enabled. 2. Browse the game resources in the "Assets" tab and select any texture or mesh for replacement. 3. Click "Save" button and navigate to "project path/Assets/Packages/mod name/" folder. Try to replicate the path to the asset that you are saving. For example, if you are saving an asset from a path "Textures/Example.png" then save it at such location "project path/Assets/Packages/mod name/Textures/Example.png". It's not always necessary to replicate the hierarchy, but it's much cleaner this way. 4. Modify exported asset as wanted. 5. It's ready. Click "Play" in Unity Editor. Notice that the UBOAT Inspector exported selected resource along with a ".meta" file. This file is important. If you would like to copy this resource manually between projects using Windows Explorer, be sure to copy it with this file as it contains GUID for this asset. Some assets may be loaded using their path, if it's highly specific, but most of them are identified by the game by their GUIDs. Creating prefabs Prefabs are named objects that may be instantiated during game execution in many copies. Some examples of prefabs in the game include ships, special effects or equipment installed on ships. If you are new to Unity, you can read about it in Unity documentation. You are free to both create new prefabs as well as replace those present in the base game. While creating prefabs nothing has to be done differently than during normal Unity use except a few things: * Prefer to store prefabs in "Assets/Packages/mod_name" folder. This way they will be correctly packed into an asset bundle and both the base game and your own scripts will be able to locate it. * Prefer to store all dependencies of your prefabs like materials and textures in this folder too. Other mods will be able to use or replace these dependencies from your mod. * Always assign "Standard (DWS)" shader to all your materials instead of the default "Standard" shader. UBOAT uses custom render pipeline and these default shaders won't render in the scene. * Texture channels used by this shader are: ** PBR Albedo/Color (RGB) + Alpha (A). ** PBR Metallicity ® + Occlusion (G) + PBR Smoothness (A). ** Height ®. It's recommended to import them as a "Single Channel" texture in Unity. It decreases memory usage and fixes potential problems with a color space. ** Normal Map (RGB). You can download our Substance Painter preset here: link. To reference an asset from the base game without duplicating it in your mod, for example base game textures for your material, extract these textures using "Modding Tools" mod to "Assets/Packages/game bundle name/path to this texture here". You can then link these textures normally to your material. This workflow won't duplicate them in your mod, but instead the newest versions of these textures will always be loaded instead, either from the base game or other mod that replaces them. Try to not duplicate base game assets in your mod without a reason, as that will increase memory usage of the game and make your mod less compatible with game updates and the work of other modders. Modding game world Groups & entities Groups contain multiple entities that are spawned into the game's scene when player approaches a group on the map. Examples of groups in the game are convoys, ports, aerial patrols. Entities are objects that have persistent state in the game world, can be detected by the player and are contained together in a group. Examples of them include ships, aircraft, launched torpedoes and ports. When they are not spawned (away from the player), they exist in a simplified form that allows player's PC to handle them in thousands without impacting performance or memory usage. When they are spawned, their 3D model appears in the scene along with a much better simulation. Define groups & entities To define a static, public group in the game world (like a new port), you will have to edit Sandbox.xlsx file. This sheet contains "Static Groups" and "Static Entities" tabs where you can place your custom objects or edit existing ones. Entity types Each entity in the world needs a specified type. Examples of entity types include Liberty ships, F-class destroyers, VIIC u-boats etc. New entity types can be defined in Entities.xlsx file. Most of the parameters are self-explaining and/or can be copied from other entries. Creating ships and aircraft Prefabs are the best way to represent ships and aircraft. Creation of new ships is a lengthy process, especially if your goal is to create a ship that supports all game features like hull cracking and LOD system to maximize performance. We created a dedicated tool to streamline this process. It can be accessed by clicking "Window/Ship Designer" menu item in the editor that is present in the Unity mod template. This tool will guide you through common optimizations and will suggest a optimal hierarchy for your prefab. To get started with it, create a new, empty game object and add (only one): - NonPlayableShip component to it, if you are creating a ship. - Aircraft component, if you work on an aircraft. - Observator component, if you work on different types of objects that shouldn't use neither a ship or aircraft AI (all ports). - Entity component, if you work on the most basic types of objects that can be detected by the player, but they don't detect other units themselves (examples: torpedoes, buoys). To associate your newly created prefab with a specific entity type defined in the game data sheets, place your prefab in "Entities" folder inside your mod's Packages folder and name it exactly like the entity type that you defined in Entities.xlsx. Creating scenes Scenes are the best choice for adding new ports and other static objects to the game. They can use lightmaps, static batching, occlusion and other features in Unity that are designed for static objects. Unlike prefabs, there can only be one scene loaded at a time. You should avoid placing multiple scenes closely one to another in the game world and prefer to merge them into one scene in such cases. Ports are large and complex objects. Currently, the best way to get started with them is to use Saint-Nazaire mod sources and build on top of it. To associate your scene with a specific entity type defined in the data sheet, name your scene exactly like the entity type defined in Entities.xlsx. Unity doesn't support placing scenes with other assets in one asset bundle, so be sure to place the scene in its own asset bundle. You can do it, using this dropdown in the editor: Scripting Introduction To create scripting mods, use of C# language will be required. Setup It's strongly recommended to create an assembly definition file for each mod in the project. To do this, navigate to "Assets/Mods/mod_name" folder that contains your mod in the "Project" tab, click right mouse button anywhere on the empty space in the panel on the right and select "Create/Assembly Definition File" from the context menu. You can name your assembly definition file in any way, but avoid characters restricted by NTFS file system. This name has to be unique across all mods. If two mods would use the same name for their assemblies, game would attempt to compile them both to the same DLL file, which isn't possible. It's the only step required to start scripting in Unity. You can click "Assets/Open C# Project" from the menu to open your code editor. If you work with Visual Studio, ensure that you have Visual Studio 2019 Tools for Unity installed. This plugin adds support for editing shader files and makes it much easier to work with Unity projects. Script files All mod scripts should be placed at "Assets/Mods/mod_name/Source" folder in a raw form (.cs files). Game compiles them on the fly using Microsoft's Roslyn compiler to a managed DLL. Prebuilt DLL-s cannot be sent to Steam Workshop and they aren't recognized by the game for security reasons. Security restrictions By default, mod scripts cannot access certain namespaces to provide a basic layer of security. You can still however ask the player for a permission to use them, by editing Manifest.json file supplied with the mod. To do so, add "permissions" field to this file and declare which permissions your mod needs to work. Currently possible requests are: * "IO": System.IO.* namespaces. * "Reflection": System.Reflection.* namespaces and Harmony library. * "Net": System.Net.* namespaces. * "NativeAccess": System.Runtime.InteropServices.* namespaces and unsafe/native code. Working with game scripts Launch callback To get a callback when your mod is launched by the game, implement UBOAT.ModAPI.IUserMod in any class of your mod. This class will be instantiated at startup and its OnLoaded method will be called. Injection framework Game extensively uses a custom injection framework. It's necessary to use it to access most of the game's singleton classes. It's used by decorating private static fields with Inject attribute like in the example below: using UBOAT.ModAPI; using UBOAT.ModAPI.Core; using UBOAT.ModAPI.Core.InjectionFramework; using UBOAT.ModAPI.UI; public class HelloWorld : BackgroundTaskBase { Inject private static IExecutionQueue executionQueue; Inject private static INotificationBarUI notificationBarUI; public override void Start() { executionQueue.AddTimedUpdateListener(DoUpdate, 5.0f); } private static float DoUpdate() { notificationBarUI.Open(null, "Hello World!"); return 5.0f; } protected override void OnFinished() { executionQueue.RemoveTimedUpdateListener(DoUpdate); } } You can then be sure that the decorated field will contain a valid reference to the needed singleton. If the requested singleton doesn't exist at the time of instantiation of your class, it will be injected instantly after its creation. For example, notification bar injected above exists only during active gameplay session. This field will contain null at the menu, but it will always point to a valid object when actual gameplay is running. You can create your own implementations of base game interfaces and replace in-game behavior or UI, although it may be troubling, while the game remains in Early Access, due to the undergoing work on the game and possible compatibility problems after updates. Execution queue To get reliable callbacks each frame, at time intervals or at a chosen date in the game's world, you may want to use built-in IExecutionQueue singleton. Instantiation To instantiate new Unity objects (for example: GameObjects) use ResourceManager.Instantiate method. This method ensures that your object is handled properly by the game and raises useful events. Use of "UnityEngine.Object.Instantiate" is blocked in the compiler. Harmony UBOAT is open for the use of Harmony library and it's supplied with the game. By using this library you can override or alter behavior of the base game code. To learn how to use Harmony, please visit its page on github. To inspect the game code, you can use dotPeek or similar tools. Background tasks Background tasks are a good and moddable way to perform general work or add custom singletons that have a well defined life cycle. To create such task, first inherit a class from UBOAT.ModAPI.Core.BackgroundTaskBase class like in the example above. Then you will have to define your new task in the game data sheets. Create "General.xlsx" data sheet in "Data Sheets" folder inside your mod and declare your task there like this: Run the game and your task should execute. If you would like your task state to be stored in the game states, decorate the class with System.Serializable attribute. Such tasks are created only once when the game campaign starts and their state is fully restored after each reload. Tasks that are not serializable are instead instantiated from the scratch each time. Periodic missions To create your own mission that may be randomly started during a patrol, create a class that derives from PeriodicSandboxMission. You will have to implement a few methods from the base class. float GetActivationWeight(IPlayerEntity target) This method should return a probability for the mission to be started at the current time. You should check, if there are valid targets for your mission inside this method and if there are none, return 0.0 to be sure that it won't start in a wrong moment. void OnMissionStarted() This metod is called, if your mission was selected to be started. In this method, you should usually send player a radio message from the HQ, to let him know that there is a mission to be done. void OnMissionFinished() You should clean up after your mission there. Be sure to remove all event listeners and registered callbacks. Warning: This section is incomplete. We will publish mission samples soon. Upload your mod to Steam Workshop Follow instructions below to send your mod to Steam Workshop. It won't immediately publish your mod and you will be able to setup Steam Workshop page for your creation. # Right-click on your mod on the list and choose "Upload to Steam Workshop" option. # Accept legal notice. # Click "Send". # Done! At this point, your mod will appear in Steam Workshop, but it will be visible only to you. You can edit its page, upload more screenshots and publish it at any time.